package com.maybach.core.dubbo.consumer.monitor;

import com.alibaba.dubbo.rpc.service.EchoService;
import com.maybach.core.dubbo.consumer.annotation.Monitor;
import com.maybach.redis.IRedisRepository;
import com.maybach.redis.RedisConstants;
import com.maybach.util.SmsOperatorsUtil;
import com.maybach.util.SpringContextUtil;
import com.maybach.util.StringUtil;
import com.maybach.util.sms.support.BizResult;
import org.apache.commons.lang3.StringUtils;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.net.InetAddress;
import java.net.UnknownHostException;
import java.lang.Object;

/**
 * Created by weishuai on 16/1/22.
 */
@Component
@Aspect
public class DubboMonitor {
    private Logger log = LoggerFactory.getLogger(this.getClass());
    private final String MOBILE = "18668123865";
    private final String MAYBACH = "【卖好车(mayBach)dubbo异常】";


    @Autowired
    private String maybachEnv;

    @Autowired
    private IRedisRepository redisRepository;


    /**
     * @param pjd
     * @param monitor
     * @return
     * @Around(value = "within(*.dubbo.consumer.*) && @annotation(monitor)")
     */
    @Around(value = "@within(monitor)")
    public Object aroundMethod(ProceedingJoinPoint pjd, Monitor monitor) {
        Object result = null;
        preHandle(monitor);
        try {
            result = pjd.proceed();
        } catch (Throwable e) {
            log.error("error in DubboMonitor." + pjd.getSourceLocation() + "业务处理异常,args" + pjd.getArgs() + "serviceName:" + monitor.serviceName() + ",desc" + monitor.desc(), e);
        }
        return result;
    }

    /**
     * 预处理
     *
     * @param monitor
     */
    private void preHandle(Monitor monitor) {
        if (monitor == null) {
            return;
        }
        String serviceName = monitor.serviceName();
        if (StringUtils.isNotBlank(serviceName)) {
            EchoService echoService = null;
            try {
                //1.获取dubbo服务实例
                echoService = (EchoService) SpringContextUtil.getBean(monitor.serviceName());
            } catch (Exception e) {
                StringBuffer sb = new StringBuffer();
                sb.append("(ip:").append(getLocalhost()).append(")调用失败;配置错误?benName:").append(serviceName).append(",desc:").append(monitor.desc());
                log.error(sb.toString(), e);
                sendMobile(MOBILE, sb.toString(), e, monitor);
            }
            try {
                //2.dubbo服务可用性校验
                Object status = echoService.$echo("OK");
                assert ("OK".equals(status.toString()));
            } catch (Exception e) {
                StringBuffer sb = new StringBuffer();
                sb.append("(ip:").append(getLocalhost()).append(")!服务方不存在或zk是否正常!serviceName:").append(serviceName).append(",desc:").append(monitor.desc());
                log.error(sb.toString(), e);
                //3.发送短信通知
                sendMobile(MOBILE, sb.toString(), e, monitor);
            }
        }
    }

    private void sendMobile(String mobile, String content, Exception e, Monitor monitor) {
        Object object = null;
        try {
            object = redisRepository.get(RedisConstants.DUBBO_MONITOR);
        } catch (Exception e1) {
            log.error("error in redisRepository,get(),", e1);
        }
        if (object == null) {
            //同样的错误8分钟内只发一次报警短信,8分周后还有错误再发短信
            String key = RedisConstants.B2B_MONITOR_KEY + monitor.serviceName();
            if (null == redisRepository.get(key)) {
                BizResult<String> result = SmsOperatorsUtil.sendSms(maybachEnv + MAYBACH + content + StringUtil.cut(String.valueOf(e.getCause()), 500), mobile, "");
                if (result.isSuccess()) {
                    redisRepository.set(key,Boolean.TRUE.toString(), 1000 * 60 * 8);
                } else {
                    log.error("error in DubboMonitor.sendMobile(),", result.getErrMsg());
                }
            }


        }
    }

    /**
     * 获取本机ip
     *
     * @return
     */
    private String getLocalhost() {
        String ip = "";
        try {
            InetAddress addr = InetAddress.getLocalHost();
            ip = addr.getHostAddress().toString();
        } catch (UnknownHostException e) {
            log.error("dubbo获取ip失败,DubboMonitor.getLocalhost()", e);
        }
        return ip;
    }
}
